package edu.cn.nlsde.tmfst.mlda;

public class DsparseTM implements Runnable {

    //    class ModelParams {
//        // hyper parameters
//        public double s;
//        public double r;
//
//        //
//        public double x;
//        public double y;
//
//        //
//        public double pi;
//        public double pi_;
//
//        //
//        public double omega;
//        public double omega_;
//
//        public int T;
//
//        public List<double[][]> gamma;
//
//        public double[][] alpha;
//
//        public double[][] beta;
//    }
//
//    class Counts {
//        public double[][] m_njk; // D * T
//        public double[] m_nj;    // 1 * D
//        public double[][] m_nkw; // T * W
//        public double[] m_nk;    // 1 * T
//
//        public double[] m_aj; // 1 * D
//        public double[] m_bk; // 1 * T
//    }
//
//    class Dataset {
//        public int D;
//        public int W;
//        public int[] Md;
//        public List<int[]> docs_w;
//        public List<int[]> docs_c;
//    }
//
//    class GibbsCounts {
//        public int[][] nw;
//        public int[][] nd;
//        public int[] nwsum;
//        public int[] ndsum;
//
//        public List<HashSet<Integer>> aj;
//        public List<HashSet<Integer>> bk;
//    }
//
//    class GibbsDataset {
//        public int D;
//        public int W;
//        public List<int[]> docs;
//        public HashMap<String, Integer> w2i;
//        public HashMap<Integer, String> i2w;
//    }
//
//    public int maxiter = 200;
//    public int saveStep = 1000;
//    public double convtol = -1;
//
//    public GibbsDataset g_ds;
//    public GibbsCounts g_c;
//    public Dataset ds;
//    public Counts c;
//    public ModelParams mp;
//    public String rootPath;
//    public String filePath;
//    public String ParentFile;
//    public int ntopics;
//
//    public DsparseTM(String rootpath, String filePath, int ntopics, int niters, int saveStep) {
//        g_ds = new GibbsDataset();
//        g_c = new GibbsCounts();
//        ds = new Dataset();
//        c = new Counts();
//        mp = new ModelParams();
//        this.rootPath = rootpath;
//        this.filePath = filePath;
//        this.maxiter = niters;
//        this.saveStep = saveStep;
//        Path sfile = java.nio.file.Paths.get(filePath);
//        this.ParentFile = java.nio.file.Paths.get(sfile.getParent().toString(), "DsparseTM_" + niters + "/" + this.rootPath).toString() + "/";
//
//        File tfg = new File(this.ParentFile);
//        if (!tfg.exists() || !tfg.isDirectory())
//            tfg.mkdirs();
//
//        this.ntopics = ntopics;
//    }
//
//    public void setModelParams() {
//        mp.T = 20;
//
//        mp.x = 1.0;
//        mp.y = 1.0;
//        mp.s = 1.0;
//        mp.r = 1.0;
//        mp.pi = 0.1;
//        mp.pi_ = 1e-7;
//        mp.omega = 0.01;
//        mp.omega_ = 1e-7;
//    }
//
//    // load GibbsDataset by reading plant text file
//    public void loadGibbsDataset(String filePath) {
//        g_ds.D = 0;
//        g_ds.W = 0;
//        g_ds.docs = new ArrayList<int[]>();
//        g_ds.w2i = new HashMap<String, Integer>();
//        g_ds.i2w = new HashMap<Integer, String>();
//
//        BufferedReader reader = IOUtil.getReader(filePath, "utf-8");
//        String lineDoc = null;
//
//        try {
//            lineDoc = reader.readLine();
//            while (lineDoc != null) {
//                String[] words = lineDoc.trim().split(" ");
//                int[] word_ids = new int[words.length];
//                for (int i = 0; i != words.length; i++) {
//                    if (!g_ds.w2i.containsKey(words[i])) {
//                        g_ds.w2i.put(words[i], g_ds.w2i.size());
//                        g_ds.i2w.put(g_ds.w2i.get(words[i]), words[i]);
//                    }
//                    word_ids[i] = g_ds.w2i.get(words[i]);
//                }
//                g_ds.docs.add(word_ids);
//                lineDoc = reader.readLine();
//            }
//            g_ds.D = g_ds.docs.size();
//            g_ds.W = g_ds.w2i.size();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    public void convert_dataset() {
//        ds.D = g_ds.D;
//        ds.W = g_ds.W;
//        ds.Md = new int[ds.D];
//        ds.docs_w = new ArrayList<int[]>();
//        ds.docs_c = new ArrayList<int[]>();
//
//        for (int j = 0; j != g_ds.docs.size(); j++) {
//            HashMap<Integer, Integer> i2c = new HashMap<Integer, Integer>();
//            for (int i = 0; i != g_ds.docs.get(j).length; i++) {
//                int w = g_ds.docs.get(j)[i];
//                if (!i2c.containsKey(w))
//                    i2c.put(w, 1);
//                else
//                    i2c.put(w, i2c.get(w) + 1);
//            }
//            ds.Md[j] = i2c.size();
//            int[] docs_w = new int[i2c.size()];
//            int[] docs_c = new int[i2c.size()];
//            int k = 0;
//            for (int wid : i2c.keySet()) {
//                docs_w[k] = wid;
//                docs_c[k] = i2c.get(wid);
//                k++;
//            }
//            ds.docs_w.add(docs_w);
//            ds.docs_c.add(docs_c);
//        }
//    }
//
//    public void initGibbsCounts() {
//        int T = mp.T;
//        int D = g_ds.D;
//        int W = g_ds.W;
//
//        g_c.nd = new int[D][T];
//        g_c.nw = new int[W][T];
//        g_c.nwsum = new int[T];
//        g_c.ndsum = new int[D];
//
//        g_c.aj = new ArrayList<HashSet<Integer>>();
//        g_c.bk = new ArrayList<HashSet<Integer>>();
//
//        for (int k = 0; k != T; k++) {
//            g_c.bk.add(new HashSet<Integer>());
//            g_c.nwsum[k] = 0;
//            for (int j = 0; j != D; j++) {
//                if (k == 0) {
//                    g_c.aj.add(new HashSet<Integer>());
//                    g_c.ndsum[j] = 0;
//                }
//                g_c.nd[j][k] = 0;
//            }
//            for (int w = 0; w != W; w++) {
//                g_c.nw[w][k] = 0;
//            }
//        }
//
//
//    }
//
//    public void gibbs_online_init() {
//        this.initGibbsCounts();
//
//        int T = mp.T;
//        int D = g_ds.D;
//        int W = g_ds.W;
//
//        double x = mp.x;
//        double y = mp.y;
//        double s = mp.s;
//        double r = mp.r;
//        double pi = mp.pi;
//        double pi_ = mp.pi_;
//        double omega = mp.omega;
//        double omega_ = mp.omega_;
//
//        double[] p = new double[T];
//        for (int j = 0; j != D; j++) {
//            for (int i = 0; i != g_ds.docs.get(j).length; i++) {
//                int w = g_ds.docs.get(j)[i];
//
//                for (int k = 0; k != T; k++) {
//                    p[k] = (g_c.nw[w][k] + omega) / (g_c.nwsum[k] + W * omega) *
//                            (g_c.nd[j][k] + pi);
//                }
//                for (int k = 1; k != T; k++) {
//                    p[k] += p[k - 1];
//                }
//                double u = Math.random() * p[T - 1];
//                for (int k = 0; k != T; k++) {
//                    if (p[k] > u) {
//                        g_c.nw[w][k]++;
//                        g_c.nd[j][k]++;
//                        g_c.nwsum[k]++;
//                        g_c.ndsum[j]++;
//
//                        g_c.aj.get(j).add(k);
//                        g_c.bk.get(k).add(w);
//                        break;
//                    }
//                }
//            }
//        }
//
//        mp.gamma = new ArrayList<double[][]>();
//        for (int j = 0; j != D; j++) {
//            int Md = ds.Md[j];
//            double[][] gamma = new double[T][Md];
//            for (int i = 0; i != Md; i++) {
//                int w = ds.docs_w.get(j)[i];
//                double normsum = 0;
//                for (int k = 0; k != T; k++) {
//                    gamma[k][i] = (g_c.nw[w][k] + omega)
//                            / (g_c.nwsum[k] + W * omega)
//                            * (g_c.nd[j][k] + pi);
//                    normsum += gamma[k][i];
//                }
//                // Normalize
//                for (int k = 0; k != T; k++) {
//                    gamma[k][i] /= normsum;
//                }
//            }
//            mp.gamma.add(gamma);
//        }
//
//        c.m_njk = new double[D][T];
//        c.m_nkw = new double[T][W];
//        c.m_nk = new double[T];
//        c.m_nj = new double[D];
//        for (int d = 0; d != D; d++) {
//            for (int t = 0; t != T; t++) {
//                if (t == 0) {
//                    c.m_nj[d] = 0.0;
//                }
//                c.m_njk[d][t] = 0.0;
//            }
//        }
//
//        for (int t = 0; t != T; t++) {
//            for (int w = 0; w != W; w++) {
//                if (w == 0) {
//                    c.m_nk[t] = 0.0;
//                }
//                c.m_nkw[t][w] = 0.0;
//            }
//        }
//
//        for (int j = 0; j != D; j++) {
//            for (int i = 0; i != ds.Md[j]; i++) {
//                int w = ds.docs_w.get(j)[i];
//                int ct = ds.docs_c.get(j)[i];
//                for (int k = 0; k != T; k++) {
//                    double mc = ct * mp.gamma.get(j)[k][i];
//                    c.m_njk[j][k] += mc;
//                    c.m_nkw[k][w] += mc;
//                    c.m_nk[k] += mc;
//                    c.m_nj[j] += mc;
//                }
//            }
//        }
//
//        mp.alpha = new double[D][T];
//        double logGamma_pi_plus_pi_ = Gamma.logGamma(pi + pi_);
//        for (int j = 0; j != D; j++) {
//            double aj = g_c.aj.get(j).size();
//            double normsum = 0.0;
//            for (int k = 0; k != T; k++) {
//                double a_jk_1 = 0.0;
//                a_jk_1 += Math.log(r + aj);
//                a_jk_1 += Gamma.logGamma(c.m_njk[j][k] + pi + pi_);
//                a_jk_1 += Beta.logBeta(pi + T * pi_ + pi * aj
//                        , c.m_nj[j] + pi * aj + T * pi_);
//                a_jk_1 = Math.exp(a_jk_1);
//
////				a_jk_1 = (r + aj) * Gamma.gamma(c.m_njk[j][k] + pi + pi_)
////						* Math.exp(Beta.logBeta(pi + T*pi_ + pi*aj, c.m_nj[j] + pi*aj + T*pi_));
//
//                double a_jk_0 = 0.0;
//                a_jk_0 += Math.log(s + T - 1 - aj) + logGamma_pi_plus_pi_;
//                a_jk_0 += Beta.logBeta(T * pi_ + pi * aj
//                        , c.m_nj[j] + pi + pi * aj + T * pi_);
//                a_jk_0 = Math.exp(a_jk_0);
//
////				a_jk_0 = (s + T - 1 - aj) * Gamma.gamma(pi + pi_)
////						* Math.exp(Beta.logBeta(T*pi_ + pi*aj, c.m_nj[j] + pi + pi*aj + T*pi_));
//
//                if (Double.isInfinite(a_jk_1)) {
//                    //System.out.println("inf a 1");
//                    mp.alpha[j][k] = 1.0;
//                } else {
//                    mp.alpha[j][k] = a_jk_1 / (a_jk_1 + a_jk_0);
//                }
//                normsum += mp.alpha[j][k];
//            }
////			for (int k = 0; k != T; k++) {
////				mp.alpha[j][k] /= normsum;
////			}
//        }
//
//        c.m_aj = new double[D];
//        for (int j = 0; j != D; j++) {
//            c.m_aj[j] = 0;
//            for (int k = 0; k != T; k++) {
//                c.m_aj[j] += mp.alpha[j][k];
//            }
//        }
//
//        mp.beta = new double[T][W];
//        double logGamma_omega_plus_omega_ = Gamma.logGamma(omega + omega_);
//        for (int k = 0; k != T; k++) {
//            double bk = g_c.bk.get(k).size();
//            double normsum = 0.0;
//            for (int w = 0; w != W; w++) {
//                double b_kr_1 = 0.0;
//                b_kr_1 += Math.log(x + bk) + Gamma.logGamma(c.m_nkw[k][w] + omega + omega_);
//                b_kr_1 += Beta.logBeta(omega + W * omega_ + omega * bk
//                        , c.m_nk[k] + omega * bk + W * omega_);
//                b_kr_1 = Math.exp(b_kr_1);
//
////				b_kr_1 = (x + bk) * Gamma.gamma(c.m_nkw[k][w] + omega + omega_)
////						*Math.exp(Beta.logBeta(omega + W * omega_ + omega * bk, c.m_nk[k] + omega * bk + W * omega_));
//
//                double b_kr_0 = 0.0;
//                b_kr_0 += Math.log(y + W - 1 - bk) + logGamma_omega_plus_omega_;
//                b_kr_0 += Beta.logBeta(W * omega_ + omega * bk
//                        , c.m_nk[k] + omega + omega * bk + W * omega_);
//                b_kr_0 = Math.exp(b_kr_0);
//
////				b_kr_0 = (y + W - 1 - bk) * Gamma.gamma(omega + omega_)
////						* Math.exp(Beta.logBeta(W * omega_ + omega * bk, c.m_nk[k] + omega + omega * bk + W * omega_));
//                if (Double.isInfinite(b_kr_1)) {
////					System.out.println("inf b 1");
//                    mp.beta[k][w] = 1.0;
//                } else {
//                    mp.beta[k][w] = b_kr_1 / (b_kr_1 + b_kr_0);
//                }
//                normsum += mp.beta[k][w];
//            }
////			for (int w = 0; w != W; w++) {
////				mp.beta[k][w] /= normsum;
////			}
//        }
//
//        c.m_bk = new double[T];
//        for (int k = 0; k != T; k++) {
//            c.m_bk[k] = 0;
//            for (int w = 0; w != W; w++) {
//                c.m_bk[k] += mp.beta[k][w];
//            }
//        }
//    }
//
//    public double dsparsetm_infer() {
//        int D = ds.D;
//        int T = mp.T;
//        int W = ds.W;
//
//        double x = mp.x;
//        double y = mp.y;
//        double s = mp.s;
//        double r = mp.r;
//        double pi = mp.pi;
//        double pi_ = mp.pi_;
//        double omega = mp.omega;
//        double omega_ = mp.omega_;
//
//        double normsum;
//
//        double logGamma_pi_plus_pi_ = Gamma.logGamma(pi + pi_);
//        for (int j = 0; j != D; j++) {
////			normsum = 0.0;
//            for (int k = 0; k != T; k++) {
//                c.m_aj[j] -= mp.alpha[j][k];
//                double aj = c.m_aj[j];
//                double njk = c.m_njk[j][k];
//                double nj = c.m_nj[j];
//                double a_jk_1 = 0.0;
//                a_jk_1 += Math.log(r + aj);
//                a_jk_1 += Gamma.logGamma(njk + pi + pi_);
//                a_jk_1 += Beta.logBeta(pi + T * pi_ + pi * aj
//                        , nj + pi * aj + T * pi_);
//                a_jk_1 = Math.exp(a_jk_1);
//
////				a_jk_1 = (r + aj) * Gamma.gamma(njk + pi + pi_)
////						* Math.exp(Beta.logBeta(pi + T*pi_ + pi*aj, nj + pi*aj + T*pi_));
//
//                double a_jk_0 = 0.0;
//                a_jk_0 += Math.log(s + T - 1 - aj) + logGamma_pi_plus_pi_;
//                a_jk_0 += Beta.logBeta(T * pi_ + pi * aj
//                        , nj + pi + pi * aj + T * pi_);
//                a_jk_0 = Math.exp(a_jk_0);
//
////				a_jk_0 = (s + T - 1 - aj) * Gamma.gamma(pi + pi_)
////						* Math.exp(Beta.logBeta(T*pi_ + pi*aj, nj + pi + pi*aj + T*pi_));
//
//                if (Double.isInfinite(a_jk_1)) {
//                    //System.out.println("inf a 2");
//                    mp.alpha[j][k] = 1.0;
//                } else {
//                    mp.alpha[j][k] = a_jk_1 / (a_jk_1 + a_jk_0);
//                }
////				normsum += mp.alpha[j][k];
//            }
//            for (int k = 0; k != T; k++) {
////				mp.alpha[j][k] /= normsum;
//                c.m_aj[j] += mp.alpha[j][k];
//            }
//        }
//
//        double logGamma_omega_plus_omega_ = Gamma.logGamma(omega + omega_);
//        for (int k = 0; k != T; k++) {
////			normsum = 0.0;
//            for (int w = 0; w != W; w++) {
//                c.m_bk[k] -= mp.beta[k][w];
//                double bk = c.m_bk[k];
//                double b_kr_1 = 0.0;
//                double nkw = c.m_nkw[k][w];
//                double nk = c.m_nk[k];
//
//                b_kr_1 += Math.log(x + bk) + Gamma.logGamma(nkw + omega + omega_);
//                b_kr_1 += Beta.logBeta(omega + W * omega_ + omega * bk
//                        , nk + omega * bk + W * omega_);
//                b_kr_1 = Math.exp(b_kr_1);
//
////				b_kr_1 = (x + bk) * Gamma.gamma(nkw + omega + omega_)
////						*Math.exp(Beta.logBeta(omega + W*omega_ + omega*bk, nk + omega*bk + W*omega_));
//
//                double b_kr_0 = 0.0;
//                b_kr_0 += Math.log(y + W - 1 - bk) + logGamma_omega_plus_omega_;
//                b_kr_0 += Beta.logBeta(W * omega_ + omega * bk
//                        , nk + omega + omega * bk + W * omega_);
//                b_kr_0 = Math.exp(b_kr_0);
//
////				b_kr_0 = (y + W - 1 - bk) * Gamma.gamma(omega + omega_)
////						* Math.exp(Beta.logBeta(W*omega_ + omega*bk, nk + omega + omega*bk + W*omega_));
//                if (Double.isInfinite(b_kr_1)) {
////					System.out.println("inf b 2");
//                    mp.beta[k][w] = 1.0;
//                } else {
//                    mp.beta[k][w] = b_kr_1 / (b_kr_1 + b_kr_0);
//                }
////				normsum += mp.beta[k][w];
//            }
//            for (int w = 0; w != W; w++) {
////				mp.beta[k][w] /= normsum;
//                c.m_bk[k] += mp.beta[k][w];
//            }
//        }
//
//        double max_delta = Double.MIN_VALUE; // max absolute change in gamma(convergence)
//        double cur_delta;
//        double[] old_gamma = new double[T];
//
//        for (int j = 0; j != D; j++) {
//            int Md = ds.Md[j];
//            int[] doc_w = ds.docs_w.get(j);
//            int[] doc_c = ds.docs_c.get(j);
//            double[][] gamma = mp.gamma.get(j);
//
//            for (int i = 0; i != Md; i++) {
//                int wi = doc_w[i];
//                int ci = doc_c[i];
//                for (int k = 0; k != T; k++) {
//                    double mc = -ci * mp.gamma.get(j)[k][i];
//                    c.m_njk[j][k] += mc;
//                    c.m_nkw[k][wi] += mc;
//                    c.m_nk[k] += mc;
//                    c.m_nj[j] += mc;
//                }
//                normsum = 0;
//                for (int k = 0; k != T; k++) {
//                    old_gamma[k] = gamma[k][i];
//                    double m_njk = c.m_njk[j][k];
//                    double m_nkw = c.m_nkw[k][wi];
//                    double m_nk = c.m_nk[k];
//                    double m_bk = c.m_bk[k];
//                    double newgamma = gamma[k][i] = (m_nkw + omega * mp.beta[k][wi] + omega_)
//                            / (m_nk + omega * m_bk + W * omega_)
//                            * (m_njk + pi * mp.alpha[j][k] + pi_);
//                    mp.gamma.get(j)[k][i] = newgamma;
//                    normsum += newgamma;
//                }
//                cur_delta = 0;
//                for (int k = 0; k != T; k++) {
//                    mp.gamma.get(j)[k][i] /= normsum;
//                    cur_delta += Math.abs(mp.gamma.get(j)[k][i] - old_gamma[k]);
//                }
//                if (cur_delta > max_delta)
//                    max_delta = cur_delta;
//                for (int k = 0; k != T; k++) {
//                    double mc = ci * mp.gamma.get(j)[k][i];
//                    c.m_njk[j][k] += mc;
//                    c.m_nkw[k][wi] += mc;
//                    c.m_nk[k] += mc;
//                    c.m_nj[j] += mc;
//                }
//            }
//        }
//        return max_delta;
//    }
//
//    public double[][] est_phi() {
//        int W = g_ds.W;
//        int T = mp.T;
//
//        double[][] g_phi = new double[T][W];
//        for (int k = 0; k != T; k++) {
//            for (int w = 0; w != W; w++) {
//                g_phi[k][w] = (c.m_nkw[k][w] + mp.omega * mp.beta[k][w] + mp.omega_)
//                        / (c.m_nk[k] + mp.omega * c.m_bk[k] + W * mp.omega_);
//            }
//        }
//        return g_phi;
//    }
//
//    public ArrayList<List<Entry<String, Double>>> sorted_topicwords(
//            double[][] phi) {
//        ArrayList<List<Entry<String, Double>>> res = new ArrayList<List<Entry<String, Double>>>();
//
//        for (int k = 0; k != mp.T; k++) {
//            HashMap<String, Double> term2weight = new HashMap<String, Double>();
//            for (String term : g_ds.w2i.keySet())
//                term2weight.put(term, phi[k][g_ds.w2i.get(term)]);
//
//            List<Entry<String, Double>> pairs = new ArrayList<Entry<String, Double>>(
//                    term2weight.entrySet());
//            Collections.sort(pairs, new Comparator<Entry<String, Double>>() {
//                public int compare(Entry<String, Double> o1,
//                                   Entry<String, Double> o2) {
//                    return (o2.getValue().compareTo(o1.getValue()));
//                }
//            });
//
//            res.add(pairs);
//        }
//
//        return res;
//    }
//
//    public void print_topics(int top_n) {
//        double phi[][] = this.est_phi();
//        ArrayList<List<Entry<String, Double>>> pairs_list = this
//                .sorted_topicwords(phi);
//        for (int k = 0; k != mp.T; k++) {
//            System.out.println("Topic " + k + ":");
//            for (int i = 0; i != top_n; i++) {
//                System.out.println(pairs_list.get(k).get(i).getKey() + " "
//                        + pairs_list.get(k).get(i).getValue());
//            }
//        }
//    }
//
//    public void save_phi(String outdir, String model_name) {
//        double[][] phi = this.est_phi();
//
//        double T = mp.T;
//        double W = ds.W;
//
//        BufferedWriter writer = IOUtil.getWriter(outdir + model_name + ".phi");
//        try {
//            for (int k = 0; k != T; k++) {
//                for (int w = 0; w != W; w++) {
//                    writer.append(phi[k][w] + " ");
//                }
//                writer.append("\n");
//            }
//            writer.flush();
//            writer.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    public double[][] est_theta() {
//        int D = g_ds.D;
//        int T = mp.T;
//
//        double[][] g_the = new double[D][T];
//        for (int d = 0; d != D; d++) {
//            for (int t = 0; t != T; t++) {
//                g_the[d][t] = (c.m_njk[d][t] + mp.pi * mp.alpha[d][t] + mp.pi_)
//                        / (c.m_nj[d] + mp.pi * c.m_aj[d] + T * mp.pi_);
//            }
//        }
//        return g_the;
//    }
//
//    public void save_wordmap(String outdir) {
//        BufferedWriter writer = IOUtil.getWriter(outdir + "wordmap.txt");
//
//        try {
//            writer.append(g_ds.w2i.size() + "\n");
//            for (String term : g_ds.w2i.keySet())
//                writer.append(term + " " + g_ds.w2i.get(term) + "\n");
//
//            writer.flush();
//            writer.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
    @Override
    public void run() {
//        printParams();
//        System.out.println("start " + this.rootPath);
//        Integer ntopics = this.ntopics;
//        String input = this.filePath;
//        this.setModelParams();
//        this.mp.T = ntopics;
//        this.loadGibbsDataset(input);
//        this.convert_dataset();
//        this.gibbs_online_init();
//        int si;
//        double delta; // max L1 change in any single \gamma_ij vector
//        for (si = 0; si < this.maxiter; si++) {
//            System.out.print("Thread_" + this.rootPath + ":" + si + " ... ");
//            if (si > 0 && si % saveStep == 0) {
//                storeResult(si);
//            }
//            delta = this.dsparsetm_infer();
//            System.out.println(delta + " ... ");
//            if (delta < this.convtol)
//                break;
//        }
//        storeResult(-1);
    }
//
//    public void storeResult(int num) {
//        String append = "final";
//        if (num > -1) {
//            append = num + "";
//        }
//        this.save_phi(this.ParentFile, "model-" + append);
//        this.save_wordmap(this.ParentFile);
//        this.save_theta(this.ParentFile, "model-" + append);
//        this.save_others(this.ParentFile, "model-" + append);
//        this.save_counts(this.ParentFile, "model-" + append);
//        this.print_topics(20);
//    }
//
//    public void save_counts(String outdir, String model_name) { //m_nkw
//        double T = mp.T;
//        double W = ds.W;
//
//        BufferedWriter writer = IOUtil.getWriter(outdir + "_" + model_name + ".count");
//        try {
//            for (int k = 0; k != T; k++) {
//                for (int w = 0; w != W; w++) {
//                    writer.append(c.m_nkw[k][w] + " ");
//                }
//                writer.append("\n");
//            }
//            writer.flush();
//            writer.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    public void save_theta(String outdir, String model_name) {
//        double[][] theta = this.est_theta();
//
//        double T = mp.T;
//        double D = ds.D;
//
//        BufferedWriter writer = IOUtil.getWriter(outdir + model_name + ".theta");
//        try {
//            for (int d = 0; d != D; d++) {
//                for (int t = 0; t != T; t++) {
//                    writer.append(theta[d][t] + " ");
//                }
//                writer.append("\n");
//            }
//            writer.flush();
//            writer.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    private void save_others(String parentFile2, String string) {
//        // TODO Auto-generated method stub
//
//    }
//
//    public void printParams() {
//        System.out.println("ntopics:" + this.ntopics
//                + "\tniters:" + this.maxiter
//                + "\tsaveStep:" + saveStep
//                + "\tParentFile:" + ParentFile
//        );
//    }
//
//    public static void DsparseTMs(int ntopics, int cpu, String sPath, int niters, int saveStep) {
//
//        ExecutorService excutor = Executors.newCachedThreadPool();
//        for (int i = 0; i < cpu; i++) {
//            DsparseTM onedd = new DsparseTM(i + "", sPath, ntopics, niters, saveStep);
//            excutor.submit(onedd);
//        }
//        excutor.shutdown();
//
//    }
}
